package utils;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.UUID;

public class AESUtils {
    /**
     *
     * @param encrypt_key AES 密钥
     * @param content 待加密文案
     * @param charset 字符集
     * @param fullAlg 算法/模式/补码方式 AES/CBC/PKCS5Padding
     * @return 加密后内容
     * @throws Exception
     */

    public static String encrypt(String encrypt_key,String content,String charset, String fullAlg) throws Exception {

        Cipher cipher = Cipher.getInstance(fullAlg);
        IvParameterSpec iv = new IvParameterSpec(initIv(fullAlg));
        cipher.init(Cipher.ENCRYPT_MODE,
                new SecretKeySpec(Base64.decode(encrypt_key.getBytes()), "AES"),
                iv);

        byte[] encryptBytes = cipher.doFinal(content.getBytes(charset));
        return new String(Base64.encode(encryptBytes));
    }

    /**
     * 初始向量的方法, 全部为0. 这里的写法适合于其它算法,针对AES算法的话,IV值一定是128位的(16字节).
     *
     * @param fullAlg 算法/模式/补码方式
     * @return
     * @throws GeneralSecurityException
     */
    private static byte[] initIv(String fullAlg) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance(fullAlg);
        int blockSize = cipher.getBlockSize();
        byte[] iv = new byte[blockSize];
        for (int i = 0; i < blockSize;++i) {
            iv[i] = 0;
        }
        return iv;
    }


    /**
     *
     * @param content 密文
     * @param key aes密钥
     * @param charset 字符集
     * @return 原文
     */
    public static String decrypt(String content, String key, String charset) throws Exception {

        //反序列化AES密钥
        SecretKeySpec keySpec = new SecretKeySpec(Base64.decode(key.getBytes()), "AES");

        //128bit全零的IV向量
        byte[] iv = new byte[16];
        for (int i = 0; i < iv.length; i++) {
            iv[i] = 0;
        }
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

        //初始化加密器并加密
        Cipher deCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        deCipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
        byte[] encryptedBytes = Base64.decode(content.getBytes(charset));
        byte[] bytes = deCipher.doFinal(encryptedBytes);
        return new String(bytes);


    }


    public static String genAesSecret(){
        try {
            KeyGenerator kg = KeyGenerator.getInstance("AES");
            //下面调用方法的参数决定了生成密钥的长度，可以修改为128, 192或256
            kg.init(128);
            SecretKey sk = kg.generateKey();
            byte[] b = sk.getEncoded();
            String secret = Base64.encode(b);
            return secret;
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("没有此算法");
        }
    }

    public void test() throws Exception{
        String secret = AESUtils.genAesSecret();
        System.out.println(secret);
        System.out.println(secret.length());

        String sContent = AESUtils.encrypt(secret, "zhouliangliang", "utf-8", "AES/CBC/PKCS5Padding");
        System.out.println(sContent);

        String content = AESUtils.decrypt(sContent, secret, "utf-8");
        System.out.println(content);
    }


    public static void main(String[] args) throws Exception {
//        System.out.println(UUID.randomUUID().toString().length());
//        System.out.println(String.valueOf(System.currentTimeMillis()).length());
        System.out.println(System.currentTimeMillis());
//        new AESUtils().test();
    }

}
